package com.reminis.exceldemo.service;

import com.reminis.exceldemo.entity.TextInputDataDto;
import com.reminis.exceldemo.entity.TextOrderEntry;
import com.reminis.exceldemo.entity.TextShipmentEntry;
import com.reminis.exceldemo.mapper.TextYejiMapper; // Make sure this import is correct
import com.reminis.exceldemo.util.ExcelUtils; // Add import
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils; // Add import

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors; // Add import

@Service
public class TextYejiService {

    private static final Logger log = LoggerFactory.getLogger(TextYejiService.class);

    @Autowired
    private TextYejiMapper textYejiMapper; // Inject the mapper

    /**
     * Processes and saves the pasted order data.
     * Clears the existing order table and inserts the new data.
     *
     * @param orderDataList List of DTOs from the controller.
     * @throws IllegalArgumentException if data conversion fails.
     */
    @Transactional // Ensure atomicity: either all succeed or all fail
    public void processAndSaveOrderData(List<TextInputDataDto> orderDataList) {
        if (CollectionUtils.isEmpty(orderDataList)) { // Use Spring's utility
            log.info("No order data provided to process.");
            return;
        }

        List<TextOrderEntry> entries = new ArrayList<>();
        for (TextInputDataDto dto : orderDataList) {
            String labelStr = dto.getZhonglei(); 
            String quantityStr = dto.getQuantity();
            String amountStr = dto.getAmount();

            if (labelStr == null || labelStr.trim().isEmpty() ||
                quantityStr == null || quantityStr.trim().isEmpty() ||
                amountStr == null || amountStr.trim().isEmpty()) {
                 log.warn("Skipping invalid order data row (empty fields): 行标签='{}', 数量='{}', 金额='{}'",
                          labelStr, quantityStr, amountStr);
                continue; 
            }

            labelStr = labelStr.trim();
            quantityStr = quantityStr.trim();
            amountStr = amountStr.trim();

            try {
                new BigDecimal(quantityStr); 
                new BigDecimal(amountStr);
            } catch (NumberFormatException e) {
                 log.warn("Skipping invalid order data row (non-numeric): 行标签='{}', 数量='{}', 金额='{}'",
                          labelStr, quantityStr, amountStr);
                continue; 
            }

            // Use setters with new English field names
            TextOrderEntry entry = new TextOrderEntry();
            entry.setLabel(labelStr);
            entry.setOrderQuantity(quantityStr);
            entry.setOrderAmount(amountStr);
            entries.add(entry);
        }

        if (entries.isEmpty()) {
             log.warn("No valid order entries found after processing DTO list.");
             // Consider throwing exception if needed based on requirements
             return;
        }

        // --- First, extract all labels (including potential duplicates) ---
        List<String> allLabels = entries.stream()
                                        .map(TextOrderEntry::getLabel)
                                        .collect(Collectors.toList());

        // 校验下单数据中类是否存在重复值--- Add validation: Check for case-insensitive duplicates ---
        if (!allLabels.isEmpty()) {
            List<String> duplicateLabels = ExcelUtils.findCaseInsensitiveDuplicates(allLabels);
            if (!duplicateLabels.isEmpty()) {
                // Make the error message clearer by showing unique duplicates
                String uniqueDuplicateNames = duplicateLabels.stream().map(String::toLowerCase).distinct().collect(Collectors.joining(", "));
                String allDuplicateOccurrences = String.join(", ", duplicateLabels);
                String errorMessage = String.format("下单数据中存在忽略大小写后重复的'中类': [%s]。请修正重复项: %s", 
                                                    uniqueDuplicateNames, allDuplicateOccurrences);
                log.warn(errorMessage);
                throw new IllegalArgumentException(errorMessage);
            }
             log.info("下单数据中的'中类'(行标签)无忽略大小写重复值，校验通过。");
        }
       
        // --- 新增校验：检查所有标签是否在周业绩表中存在 ---
        List<String> uniqueLabels = allLabels.stream() // Reuse the extracted list
                                         .distinct()
                                         .collect(Collectors.toList());

        if (!uniqueLabels.isEmpty()) {
            // Prepare lowercase list for case-insensitive query
            List<String> lowerCaseUniqueLabels = uniqueLabels.stream()
                                                             .map(String::toLowerCase)
                                                             .collect(Collectors.toList());
                                                             
            // Mapper now returns existing labels in lowercase
            List<String> lowerCaseExistingLabels = textYejiMapper.findExistingZhongleiInYeji(lowerCaseUniqueLabels);
            
            // Find missing labels by comparing original list against lowercase existing list
            List<String> missingLabels = uniqueLabels.stream()
                                                     .filter(label -> !lowerCaseExistingLabels.contains(label.toLowerCase()))
                                                     .collect(Collectors.toList());

            if (!missingLabels.isEmpty()) {
                String errorMessage = "以下下单数据中的'中类'在周业绩表中不存在: " + String.join(", ", missingLabels);
                log.warn(errorMessage);
                throw new IllegalArgumentException(errorMessage); // Throw exception to stop processing and inform user
            }
            log.info("所有下单数据中的 '中类' 在周业绩表中均存在，校验通过。");
        }
        // --- End validation ---

        // --- 新增：校验金额小数位数是否为3或4位 ---
        ExcelUtils.validateAmountDecimalPlaces(orderDataList, "下单数据");
        // --- 校验结束 ---

        // --- Continue with original logic if validation passes ---
        // --- 如果校验通过，继续执行原逻辑 ---
        textYejiMapper.truncateOrderTable();
        log.info("Truncated 下单表.");
        int insertedCount = textYejiMapper.batchInsertOrders(entries);
        log.info("插入下单表成功，条数为："+insertedCount);
        if (insertedCount != entries.size()) {
             log.warn("Mismatch insertions for 下单表: Expected={}, Actual={}", entries.size(), insertedCount);
             // Consider throwing exception if this mismatch is critical
        }
    }

    /**
     * Processes and saves the pasted shipment data.
     * Clears the existing shipment table and inserts the new data.
     *
     * @param shipmentDataList List of DTOs from the controller.
     * @throws IllegalArgumentException if data conversion fails.
     */
    @Transactional
    public void processAndSaveShipmentData(List<TextInputDataDto> shipmentDataList) {
         if (CollectionUtils.isEmpty(shipmentDataList)) { // Use Spring's utility
             log.info("No shipment data provided to process.");
             return;
         }

        List<TextShipmentEntry> entries = new ArrayList<>();
        for (TextInputDataDto dto : shipmentDataList) {
            String labelStr = dto.getZhonglei(); 
            String quantityStr = dto.getQuantity(); 
            String amountStr = dto.getAmount();   

             if (labelStr == null || labelStr.trim().isEmpty() ||
                 quantityStr == null || quantityStr.trim().isEmpty() ||
                 amountStr == null || amountStr.trim().isEmpty()) {
                 log.warn("Skipping invalid shipment data row (empty fields): 行标签='{}', 数量='{}', 金额='{}'",
                          labelStr, quantityStr, amountStr);
                continue; 
            }
            
            labelStr = labelStr.trim();
            quantityStr = quantityStr.trim();
            amountStr = amountStr.trim();
            
            try {
                new BigDecimal(quantityStr); 
                new BigDecimal(amountStr);
            } catch (NumberFormatException e) {
                 log.warn("Skipping invalid shipment data row (non-numeric): 行标签='{}', 数量='{}', 金额='{}'",
                          labelStr, quantityStr, amountStr);
                continue; 
            }

            // Use setters with new English field names for Shipment entry
            TextShipmentEntry entry = new TextShipmentEntry();
            entry.setLabel(labelStr); 
            // IMPORTANT: Verify these match the fields in TextShipmentEntry.java
            entry.setShipmentQuantity(quantityStr); 
            entry.setShipmentAmount(amountStr);  
            entries.add(entry);
        }
        
        if (entries.isEmpty()) {
             log.warn("No valid shipment entries found after processing DTO list.");
             // Consider throwing exception if needed
             return;
        }

        // --- 添加发货数据金额小数位数校验是否为3或4位 ---
        ExcelUtils.validateAmountDecimalPlaces(shipmentDataList, "发货数据");
        // --- 校验结束 ---

        // Extract all labels (case-insensitive) for duplicate check
        List<String> allShipmentLabels = entries.stream()
                                        .map(TextShipmentEntry::getLabel)
                                        .collect(Collectors.toList());

        // --- Add validation: Check for case-insensitive duplicates ---
        if (!allShipmentLabels.isEmpty()) {
            List<String> duplicateLabels = ExcelUtils.findCaseInsensitiveDuplicates(allShipmentLabels);
            if (!duplicateLabels.isEmpty()) {
                // Make the error message clearer by showing unique duplicates
                String uniqueDuplicateNames = duplicateLabels.stream().map(String::toLowerCase).distinct().collect(Collectors.joining(", "));
                String allDuplicateOccurrences = String.join(", ", duplicateLabels);
                String errorMessage = String.format("发货数据中存在忽略大小写后重复的'中类': [%s]。请修正重复项: %s",
                                                    uniqueDuplicateNames, allDuplicateOccurrences);
                log.warn(errorMessage);
                throw new IllegalArgumentException(errorMessage);
            }
             log.info("发货数据中的'中类'(行标签)无忽略大小写重复值，校验通过。");
        }
        // --- End duplicate check ---

        // --- 新增校验：检查所有标签是否在周业绩表中存在 --- 
        List<String> uniqueShipmentLabels = allShipmentLabels.stream()
                                          .distinct()
                                          .collect(Collectors.toList());

        if (!uniqueShipmentLabels.isEmpty()) {
            // Prepare lowercase list for case-insensitive query
            List<String> lowerCaseUniqueShipmentLabels = uniqueShipmentLabels.stream()
                                                             .map(String::toLowerCase)
                                                             .collect(Collectors.toList());
                                                             
            // Mapper now returns existing labels in lowercase
            List<String> lowerCaseExistingShipmentLabels = textYejiMapper.findExistingZhongleiInYeji(lowerCaseUniqueShipmentLabels);
            
            // Find missing labels by comparing original list against lowercase existing list
            List<String> missingShipmentLabels = uniqueShipmentLabels.stream()
                                                     .filter(label -> !lowerCaseExistingShipmentLabels.contains(label.toLowerCase()))
                                                     .collect(Collectors.toList());

            if (!missingShipmentLabels.isEmpty()) {
                String errorMessage = "以下发货数据中的'中类'在周业绩表中不存在: " + String.join(", ", missingShipmentLabels);
                log.warn(errorMessage);
                throw new IllegalArgumentException(errorMessage); // Throw exception
            }
            log.info("所有发货数据中的 '中类' 在周业绩表中均存在，校验通过。");
        }
        // --- End validation ---
        // --- 校验结束 ---

        // --- Continue with original logic if validation passes ---
        // --- 如果校验通过，继续执行原逻辑 ---
        textYejiMapper.truncateShipmentTable();
        log.info("Truncated 发货表.");
        int insertedCount = textYejiMapper.batchInsertShipments(entries);
        log.info("插入发货表成功，条数为："+ insertedCount);
        if (insertedCount != entries.size()) {
             log.warn("Mismatch insertions for 发货表: Expected={}, Actual={}", entries.size(), insertedCount);
             // Consider throwing exception if critical
        }
    }

    /**
     * Generates and updates the weekly performance (周业绩) data.
     * Steps:
     * 1. Clear statistics fields in 周业绩表.
     * 2. Update 周业绩表 with aggregated data from 下单表.
     * 3. Update 周业绩表 with aggregated data from 发货表.
     *
     * @return A message indicating the result.
     */
    @Transactional
    public String generateAndUpdateYeji() {
        log.info("Starting generation and update of 周业绩表.");
        try {
            // 清空周业绩表几个数量及金额字段
            textYejiMapper.clearYejiStats();
            log.info("Cleared statistics fields in 周业绩表.");

            // Step 2: Update from orders
            int ordersUpdated = textYejiMapper.updateYejiFromOrders();
            log.info("Updated {} 周业绩表 records based on 下单表 data.", ordersUpdated);

            // Step 3: Update from shipments
            int shipmentsUpdated = textYejiMapper.updateYejiFromShipments();
            log.info("Updated {} 周业绩表 records based on 发货表 data.", shipmentsUpdated);

            String message = String.format("周业绩表更新成功。下单数据影响 %d 条记录，发货数据影响 %d 条记录。", ordersUpdated, shipmentsUpdated);
            log.info(message);
            return message;

        } catch (Exception e) {
            log.error("Error during 周业绩表 generation/update process.", e);
            // Re-throw a runtime exception to ensure transaction rollback
            throw new RuntimeException("生成或更新周业绩数据时发生错误: " + e.getMessage(), e);
        }
    }
} 